#include "../Inc/InstanceStateMachine.h"
#include "../AppInstances/BasicFrame/BasicFrame.h"

InstanceStateMachine* InstanceStateMachine::mStateMachine = NULL;

InstanceStateMachine* InstanceStateMachine::Instance()
 {
	if (!mStateMachine)
	{
		mStateMachine = new InstanceStateMachine();
	}
	return mStateMachine;
}

InstanceStateMachine::InstanceStateMachine():mCurrentState(NULL),
	                                         mNextState(NULL),
											 mPrevState(NULL)
{
	std::string startState = "BasicFrame";
	AddState(new BasicFrame());
	TransToState(startState);
}

InstanceStateMachine::~InstanceStateMachine()
{
	InstantIter iter    =   mInsContainer.begin();
	InstantIter iter2   =   mInsContainer.end();
	while (iter2 != iter)
	{
		delete *iter;
		*iter = NULL;
		iter++;
	}
	mInsContainer.clear();
}

bool InstanceStateMachine::AddState(InstanceState* state)
{
	InstantIter iter    =   mInsContainer.begin();
	InstantIter iter2   =   mInsContainer.end();
	while (iter2 != iter)
	{
		if (0 == (*iter)->mStateName.compare(state->mStateName))
		{
			return false; //state already added..
		}
		iter++;
	}
	mInsContainer.push_back(state);//add state..
	return true;
}

bool InstanceStateMachine::DelState(const std::string& stateName)
{
	InstantIter iter    =   mInsContainer.begin();
	InstantIter iter2   =   mInsContainer.end();
	while (iter2 != iter)
	{
		if (0 == (*iter)->mStateName.compare(stateName))
		{
			mInsContainer.erase(iter); //remove the state..
			return true;
		}
		iter++;
	}
	return false;//state not found..
}

bool InstanceStateMachine::TransToState(const std::string& stateName)
{
	InstantIter iter    =   mInsContainer.begin();
	InstantIter iter2   =   mInsContainer.end();
	while (iter2 != iter)
	{
		if (0 == (*iter)->mStateName.compare(stateName))
		{
			mNextState = *iter; // transfer to the next state..
			return true;
		}
		iter++;
	}
	return false; //Not found the state..
}

void InstanceStateMachine::UpdateStateMachine(float deltaTime)
{
	if (mNextState)
	{
		if (mCurrentState)
		{
			mCurrentState->Release();      //shut down the current state..
		}
		mPrevState = mCurrentState;    //save current state to prev state..
		mCurrentState = mNextState;    //set current state to next state..
		mNextState = NULL;             //set next state null..
		mCurrentState->Init();         //init current state..
	}

	if (mCurrentState)
	{
		mCurrentState->Update(deltaTime);        //update current state..
		mCurrentState->Render();                 //render current state..
	}
}